<template>
  <div class="tableRow">
    <el-row class="select-list" v-permission="'system:user:query'">
      <el-form :inline="true" ref="selectForm" :label-position="'right'" label-width="80px"
               :model="selectFormModel" size="mini">
        <el-form-item label="用户名" prop="userName">
          <el-input v-model="selectFormModel.userName" placeholder="用户名" style="width: 200px" clearable
                    @keyup.enter.native="onSearch"/>
        </el-form-item>
        <el-form-item label="手机号码" prop="phoneNumber">
          <el-input v-model="selectFormModel.phoneNumber" placeholder="手机号码" style="width: 200px" clearable
                    @keyup.enter.native="onSearch"/>
        </el-form-item>
        <el-form-item label="性别" prop="sex">
          <el-select value="" v-model="selectFormModel.sex" placeholder="性别" style="width: 200px">
            <el-option label="男" value="0"/>
            <el-option label="女" value="1"/>
            <el-option label="保密" value="2"/>
          </el-select>
        </el-form-item>
        <el-form-item label="用户状态" prop="status">
          <el-select value="" v-model="selectFormModel.status" placeholder="用户状态" style="width: 200px">
            <el-option label="正常" value="0"/>
            <el-option label="停用" value="1"/>
          </el-select>
        </el-form-item>
        <el-form-item>
          <el-button type="primary" icon="el-icon-search" size="mini" plain round @click="onSearch">搜索
          </el-button>
          <el-button type="warning" icon="el-icon-refresh" size="mini" plain round
                     @click="onRefreshSelectForm()">重置
          </el-button>
        </el-form-item>
      </el-form>
    </el-row>
    <el-row class="toolbar">
      <el-button type="primary" icon="el-icon-plus" size="mini" plain @click="handleAdd"
                 v-permission="'system:user:add'">
        新增
      </el-button>
      <el-button type="info" icon="el-icon-edit" :disabled="dialog.isBatchEditDisabled" size="mini" plain
                 @click="handleEdit" v-permission="'system:user:edit'"> 编辑
      </el-button>
      <el-button type="danger" icon="el-icon-delete" :disabled="dialog.isBatchRemoveDisabled" size="mini" plain
                 @click="handleBatchDelete" v-permission="'system:user:remove'"> 删除
      </el-button>
      <el-button type="success" icon="el-icon-upload" size="mini" plain @click="handleImport"
                 v-permission="'system:user:import'"> 导入
      </el-button>
      <el-button type="warning" icon="fa fa-download" size="mini" plain @click="handleExport"
                 v-permission="'system:user:export'"> 导出
      </el-button>
    </el-row>
    <data-table ref="dataTable"
                :api="getUserList"
                :options="options"
                :pagination.sync="page"
                :columns="columns"
                :operates="operates"
                :query="selectFormModel"
                @handle-selection-change="handleSelectionChange"
    />

    <transition name="el-fade-in">
      <el-dialog :title="dialog.title" :visible.sync="dialog.dialogFormVisible"
                 :modal-append-to-body="false"
                 :destroy-on-close="false"
                 @close="closeDialog"
                 width="600px">
        <el-form :model="userModel" ref="userForm" label-width="100px" :rules="userFormRules" size="small ">
          <el-form-item label="用户名" prop="userName">
            <el-input v-model="userModel.userName" placeholder="用户名" :disabled="dialog.isEdit"/>
          </el-form-item>
          <el-form-item label="姓名" prop="name">
            <el-input v-model="userModel.name" placeholder="姓名"/>
          </el-form-item>

          <el-form-item label="部门" prop="deptId">
            <!--el-tree-select  文档地址 https://ayiaq1.github.io/el-tree-select/website/#/components/ElTreeSelect-->
            <el-tree-select v-model="userModel.deptId" :selectParams="dialog.selectParams"
                            :treeParams="dialog.treeParams"
                            @searchFun="searchFun" ref="treeSelect"/>
          </el-form-item>

          <el-form-item label="角色" prop="roleIds">
            <el-select value="" v-model="userModel.roleIds" multiple filterable clearable placeholder="角色">
              <el-option
                  v-for="item in dialog.roles"
                  :key="item.id"
                  :label="item.roleName"
                  :value="item.id">
              </el-option>
            </el-select>
          </el-form-item>

          <el-form-item label="岗位" prop="postIds">
            <el-select value="" v-model="userModel.postIds" multiple filterable clearable placeholder="岗位">
              <el-option
                  v-for="item in dialog.posts"
                  :key="item.id"
                  :label="item.postName"
                  :value="item.id">
              </el-option>
            </el-select>
          </el-form-item>
          <el-form-item label="状态" prop="status">
            <el-switch v-model="userModel.status" active-color="#13ce66" inactive-color="#ff4949"
                       active-text="正常"
                       inactive-text="停用"
                       active-value="0"
                       inactive-value="1"/>
          </el-form-item>
          <el-form-item label="邮箱" prop="email">
            <el-input v-model="userModel.email" placeholder="邮箱"/>
          </el-form-item>
          <el-form-item label="手机" prop="phoneNumber">
            <el-input v-model="userModel.phoneNumber" prefix-icon="el-icon-phone"
                      placeholder="手机"/>
          </el-form-item>
          <el-form-item label="性别" prop="sex">
            <el-select value="" v-model="userModel.sex" placeholder="性别">
              <el-option label="男" value="0"/>
              <el-option label="女" value="1"/>
              <el-option label="保密" value="2"/>
            </el-select>
          </el-form-item>
          <el-form-item label="备注" prop="remark">
            <el-input v-model="userModel.remark" placeholder="备注" maxlength="100"/>
          </el-form-item>
        </el-form>
        <div slot="footer" class="dialog-footer">
          <el-button @click="dialog.dialogFormVisible=false" size="medium">取 消</el-button>
          <el-button type="primary" @click="submitForm" size="medium">确 定</el-button>
        </div>
      </el-dialog>
    </transition>

    <transition name="el-fade-in">
      <el-dialog :title="dialog.title" :visible.sync="dialog.dialogImportVisible"
                 :modal-append-to-body="false"
                 :destroy-on-close="false"
                 custom-class="body-wrapper"
                 @close="closeUploadDialog"
                 width="500px">

        <el-upload
            drag
            ref="upload"
            :action="src"
            :show-file-list="true"
            :auto-upload="false"
            :headers="headers"
            accept=".xls,.xlsx"
            :on-success="uploadSuccess"
            :on-exceed="handleExceed"
            :on-error="uploadError"
            :limit="1"
        >
          <i class="el-icon-upload"/>
          <div class="el-upload__text">将文件拖到此处，或<em>点击上传</em></div>

          <div class="el-upload__tip" slot="tip">
            <el-alert
                title="只能上传xls/xlsx文件"
                type="warning"
                show-icon>
            </el-alert>
            <br/>
            <el-alert type="info"
                      show-icon
                      :closable="false">
              <span>没有模板？ 点击&nbsp;<a href="#" @click="downloadTemplate">下载模板</a></span>
            </el-alert>
          </div>
        </el-upload>

        <div slot="footer" class="dialog-footer">
          <el-button @click="dialog.dialogImportVisible=false" size="medium">取 消</el-button>
          <el-button type="primary" @click="submitUpload" size="medium">确 定</el-button>
        </div>
      </el-dialog>
    </transition>
  </div>
</template>
<script lang="ts">
//https://github.com/kaorun343/vue-property-decorator
import {Component, Ref, Vue} from 'vue-property-decorator';
import DataTable from '@/components/DataTable/DataTable.vue';
import {
  addUser,
  checkEmailUnique,
  checkPhoneUnique,
  checkUserNameUnique,
  downloadUserImportTemplate,
  exportUser,
  getUserList,
  getUserPost,
  getUserRole,
  removeUser,
  resetPwd,
  updateUser
} from '@/api/user';
import {deptTreeSelectData} from '@/api/dept';
import {getPostList} from '@/api/post';
import {getRoleList} from '@/api/role';
import axios from 'axios';
import store from '@/store';
import {validateForm} from '@/utils';

@Component({components: {DataTable}})
export default class User extends Vue {
  private getUserList: any = getUserList;
  @Ref('userForm') private userForm: any;
  @Ref('selectForm') private selectForm: any;
  @Ref('treeSelect') private treeSelect: any;
  @Ref('dataTable') private dataTable: any;
  @Ref('upload') private upload: any;

  get src() {
    return process.env.VUE_APP_BASE_API + '/system/user/import';
  }

  headers: any = {
    'Authorization': store.getters.token
  };

  columns: any = [
    {label: 'ID', prop: 'id', sortable: 'custom'},
    {label: '用户名', prop: 'userName', sortable: 'custom'},
    {label: '姓名', prop: 'name', sortable: 'custom'},
    {
      label: '部门', prop: 'dept', formatter: function (row: any, column: any) {
        if (row && row.dept && row.dept.deptName) {
          return row.dept.deptName;
        } else {
          return '无';
        }
      }
    },
    {label: '邮箱', prop: 'email', sortable: 'custom', showOverflowTooltip: true},
    {label: '手机', prop: 'phoneNumber', sortable: 'custom', showOverflowTooltip: true},
    {
      label: '性别', prop: 'sex', sortable: 'custom', formatter: function (row: any, column: any) {
        if (row && row.sex === '0') {
          return '男';
        } else if (row && row.sex === '1') {
          return '女';
        } else {
          return '保密';
        }
      }
    },
    {
      label: '状态', prop: 'status', sortable: 'custom', render: function (createElement: any, row: any) {
        if (row && row.row && row.row.status === '0') {
          return createElement('el-tag', {
                attrs: {
                  type: 'success'
                }
              }, ['正常']
          );
        } else if (row && row.row && row.row.status === '1') {
          return createElement('el-tag', {
                attrs: {
                  type: 'warning'
                }
              }, ['停用']
          );
        } else {
          return createElement('el-tag', {
                attrs: {
                  type: 'danger'
                }
              }, ['未知']
          );
        }
      }
    },
    {label: '创建时间', prop: 'createTime', sortable: 'custom', width: 160, showOverflowTooltip: true},
    {label: '备注', prop: 'remark', sortable: 'custom', showOverflowTooltip: true},
  ];

  // table 的参数
  options: any = {
    stripe: true, // 是否为斑马纹 table
    loading: false, // 是否添加表格loading加载动画
    highlightCurrentRow: true, // 是否支持当前行高亮显示
    multipleSelect: true, // 是否支持列表项选中功能
  };


  // 分页参数
  page: any = {
    pageNum: 1,
    pageSize: 10,
    pageArray: [10, 20, 50, 100]
  };

  //按钮操作组
  operates: any = {
    title: '操作',
    width: 'auto',
    fixed: 'right',
    list: [
      {
        label: '编辑',
        type: 'warning',
        icon: 'el-icon-edit',
        plain: true,
        disabled: (index: any, row: any) => {
          return row && row.id === 1;
        },
        permission: 'system:user:edit',
        method: (index: any, row: any) => {
          this.handleEdit(index, row);
        }
      },
      {
        label: '删除',
        type: 'danger',
        icon: 'el-icon-delete',
        plain: true,
        disabled: (index: any, row: any) => {
          return row && row.id === 1;
        },
        permission: 'system:user:remove',
        method: (index: any, row: any) => {
          this.handleDelete(index, row);
        }
      },
      {
        label: '重置',
        type: 'primary',
        icon: 'el-icon-key',
        plain: true,
        disabled: (index: any, row: any) => {
          return row && row.id === 1;
        },
        permission: 'system:user:edit',
        method: (index: any, row: any) => {
          this.handleReset(index, row);
        }
      }
    ]
  };
  selectFormModel: any = {
    userName: '',
    status: '',
    phoneNumber: '',
    sex: '',
  };
  dialog: any = {
    dialogFormVisible: false,
    dialogImportVisible: false,
    title: '对话框',
    isEdit: false,
    isBatchEditDisabled: true,
    isBatchRemoveDisabled: true,
    formData: {},
    selectParams: {
      clearable: true,
      placeholder: '请选择部门'
    },
    treeParams: {
      clickParent: true,
      filterable: true,
      accordion: true,
      data: [],
      props: {
        children: 'children',
        label: 'label',
        disabled: 'disabled',
        value: 'id'
      }
    }
  };

  userModel: any = {
    userName: '',
    name: '',
    email: '',
    phoneNumber: '',
    sex: '',
    deptId: '',
    roleIds: [],
    status: 0,
    remark: '',
    postIds: []
  };
  userFormRules: any = {
    userName: [
      {required: true, message: '用户名不能为空', trigger: ['blur', 'change']},
      {
        required: true,
        pattern: /^[a-zA-Z0-9_]*$/,//可以写正则表达式
        message: '用户名只能是字母或者数字',
        trigger: ['blur', 'change']
      },
      {validator: this.validateUserNameUnique, trigger: 'blur'}
    ],
    name: [
      {required: true, message: '姓名不能为空', trigger: ['blur', 'change']}
    ],
    email: [
      {required: true, message: '邮箱不能为空', trigger: ['blur', 'change']},
      {type: 'email', message: '请输入正确的邮箱地址', trigger: ['blur', 'change']},
      {validator: this.validateEmailUnique, trigger: 'blur'}
    ],
    phoneNumber: [
      {required: true, message: '手机号码不能为空', trigger: 'blur'},
      {
        required: true,
        pattern: /^1[345678]\d{9}$/,//可以写正则表达式
        message: '目前只支持中国大陆的手机号码',
        trigger: ['blur', 'change']
      },
      {validator: this.validatePhoneUnique, trigger: 'blur'}
    ],
    sex: [
      {required: true, message: '性别不能为空', trigger: ['blur', 'change']}
    ]
  };

  /*验证用户名是否唯一*/
  validateUserNameUnique(rule: any, value: any, callback: any) {
    checkUserNameUnique({
      userName: value,
      id: this.userModel.id
    }).then((res: any) => {
      if (res.data && res.data === '0') {
        callback();
      } else {
        callback(new Error('用户名已经存在'));
      }
    }).catch((err: any) => {
      console.log(err);
      callback(new Error('用户名已经存在'));
    })
  }

  /*验证手机号码是否唯一*/
  validatePhoneUnique(rule: any, value: any, callback: any) {
    checkPhoneUnique({
      phoneNumber: value,
      id: this.userModel.id
    }).then((res: any) => {
      if (res.data && res.data === '0') {
        callback();
      } else {
        callback(new Error('手机号码已经存在'));
      }
    }).catch((err: any) => {
      console.log(err);
      callback(new Error('手机号码已经存在'));
    })
  }

  /*验证邮箱是否唯一*/
  validateEmailUnique(rule: any, value: any, callback: any) {
    checkEmailUnique({
      email: value,
      id: this.userModel.id
    }).then((res: any) => {
      if (res.data && res.data === '0') {
        callback();
      } else {
        callback(new Error('邮箱已经存在'));
      }
    }).catch((err: any) => {
      console.log(err);
      callback(new Error('邮箱已经存在'));
    })
  }

  handleEdit(index: number, row: any): void {
    //编辑
    this.userModel = Object.assign({}, row || this.dialog.formData[0]);
    this.userModel.dept = [];
    this.dialog.title = '编辑用户';
    this.dialog.isEdit = true;
    const id = (row && row.id) ? row.id : this.dialog.formData[0].id;

    axios.all(
        [
          getUserRole({'id': id}),
          deptTreeSelectData(),
          getUserPost({'id': id})
        ]
    ).then(axios.spread((role: any, dept: any, post: any) => {
      if (role.data) {
        this.userModel.roleIds = role.data.roleIds;
        this.dialog.roles = role.data.roles;
      }

      if (this.userModel && this.userModel.roleIds === null) {
        this.userModel.roleIds = [];
      }
      if (dept.data) {
        this.dialog.treeParams.data = dept.data;
      }

      if (post.data) {
        this.userModel.postIds = post.data.postIds;
        this.dialog.posts = post.data.posts;
      }

      this.dialog.dialogFormVisible = true;
    })).catch((e) => {
      console.log(e);
    });
  }

  handleAdd(): void {
    //打开新增
    this.dialog.title = '新增用户';
    this.dialog.isEdit = false;

    axios.all([getRoleList({'status': 0}), deptTreeSelectData(), getPostList({'status': 0})])
        .then(axios.spread((role: any, dept: any, post: any) => {
          this.dialog.roles = role.rows;
          this.dialog.treeParams.data = dept.data;
          this.dialog.posts = post.rows;
          this.dialog.dialogFormVisible = true;
        })).catch((e) => {
      console.log(e);
    });
  }

  handleBatchDelete(): void {
    //删除
    this.$confirm('确定要删除选定用户？', '警告', {
      confirmButtonText: '确定',
      cancelButtonText: '取消',
      type: 'warning'
    }).then(() => {
      const ids: Array<any> = [];
      this.dialog.formData.forEach((item: any, index: number) => {
        ids[index] = item.id;
      });
      return removeUser({'ids': ids});
    }).then((response: any) => {
      this.dataTable.refresh();
      this.$message.success(response.msg);
    }).catch((e) => {
      console.log(e);
    });
  }

  searchFun(value: any): void {
    this.treeSelect.filterFun(value);
  }

  onSearch(): void {
    this.dataTable.refresh();
  }

  onRefreshSelectForm(): void {
    //恢复搜索默认信息
    this.selectForm.resetFields();
    this.onSearch();
  }

  closeDialog(): void {
    this.$nextTick(() => {
      this.dialog.treeParams.data = [];
      this.reset();
    });
  }

  submitForm(): void {
    this.userForm.validate((valid: boolean) => {
      if (valid) {
        this.userModel.roles = [];
        this.userModel.dept = [];
        this.userModel.posts = [];
        if (this.dialog.isEdit) {
          //编辑
          updateUser(this.userModel).then((response: any) => {
            this.dataTable.refresh();
            this.reset();
            this.dialog.dialogFormVisible = false;
            this.$message.success(response.msg);
          }).catch((e) => {
            console.log(e);
            validateForm(e.data, this.userForm, this.userFormRules);
          });
        } else {
          //新增
          addUser(this.userModel).then((response: any) => {
            this.dataTable.refresh();
            this.reset();
            this.dialog.dialogFormVisible = false;
            this.$message.success(response.msg);
          }).catch((e) => {
            console.log(e);
            validateForm(e.data, this.userForm, this.userFormRules);
          });
        }
      }
    });
  }

  handleDelete(index: number, row: any): void {
    //删除
    this.$confirm('确定要删除该用户？', '警告', {
      confirmButtonText: '确定',
      cancelButtonText: '取消',
      type: 'warning'
    }).then(() => {
      return removeUser({'ids': [row.id]});
    }).then((response: any) => {
      this.dataTable.refresh();
      this.$message.success(response.msg);
    }).catch((e) => {
      console.log(e);
    });
  }

  handleReset(index: number, row: any): void {
    //删除
    this.$confirm('确定要重置该用户的登录密码吗？', '警告', {
      confirmButtonText: '确定',
      cancelButtonText: '取消',
      type: 'warning'
    }).then(() => {
      return resetPwd({'id': row.id});
    }).then((response: any) => {
      this.dataTable.refresh();
      this.$message.success(response.msg);
    }).catch((e) => {
      console.log(e);
    });
  }

  handleSelectionChange(val: any): void {
    //返回选中对象
    if (val) {
      this.dialog.isBatchRemoveDisabled = val.length <= 0;
      this.dialog.isBatchEditDisabled = val.length !== 1;
    }
    this.dialog.formData = val;
  }

  reset(): void {
    this.userModel = {
      userName: '',
      name: '',
      email: '',
      phoneNumber: '',
      sex: '',
      deptId: '',
      roleIds: [],
      status: 0,
      remark: '',
      postIds: []
    };
    (this as any).resetForm('userForm');
  }

  /*导出excel*/
  handleExport(): void {
    this.$confirm('确定要导出当前查询的所有用户信息吗？', '提示', {
      confirmButtonText: '确定',
      cancelButtonText: '取消',
      type: 'info'
    }).then(() => {
      this.selectFormModel.pageNum = null;
      this.selectFormModel.pageSize = null;
      this.selectFormModel.orderByColumn = 'id';
      this.selectFormModel.isAsc = 'asc';

      return exportUser(this.selectFormModel);
    }).then((response: any) => {
      console.log(response);
      if (response && response.data) {
        (this as any).$download(response.data.fileName);
      }
    }).catch((e) => {
      console.log(e);
    });
  }

  /*下载用户导入模板*/
  downloadTemplate(): void {
    downloadUserImportTemplate().then((response: any) => {
      console.log(response);
      if (response && response.data) {
        (this as any).$download(response.data.fileName);
      }
    }).catch((e) => {
      console.log(e);
    });
  }

  /*打开导入对话框*/
  handleImport(): void {
    this.dialog.title = '用户导入';
    this.dialog.dialogFormVisible = false;
    this.dialog.dialogImportVisible = true;
  }

  /*上传*/
  submitUpload() {
    this.upload.submit();
  }

  /*上传成功*/
  uploadSuccess(res, file) {
    console.log(res);
    if (res.result) {//上传成功
      this.$message.success(`导入成功，${res.msg}`);
    } else {//上传失败
      this.$message.warning(`导入失败，${res.msg}`);
      this.upload.clearFiles();
    }
  }

  /*文件上传失败*/
  uploadError(res, file) {
    console.log(res.message);
    const result = JSON.parse(res.message);

    this.$message.error(`导入失败，${result.msg}`);
  }

  handleExceed(files, fileList) {
    this.$message.warning(`当前限制选择 3 个文件，本次选择了 ${files.length} 个文件，共选择了 ${files.length + fileList.length} 个文件`);
  }

  closeUploadDialog() {
    this.$nextTick(() => {
      this.upload.clearFiles();
    });
  }
}
</script>

<style scoped lang="scss">
a {
  color: #8c939d;

  &:hover {
    color: #b4bccc;
    text-decoration: underline;
  }
}
</style>

